/** 
* @file vmu.h
* Virtual Memory Unit (header declarations).
* Unit for virtual memory managment: page directory, page table,
* page allocation.
*
* Copyrights 2010 Michal Saman, m.saman@designplus.cz.
* This source code is release under the Apache License 2.0.
* http://www.apache.org/licenses/LICENSE-2.0
*/

#ifndef _VMU_H
#define _VMU_H

#include <stdint.h>
#include <mem/pmu.h>
#include <mem/vmu_pte.h>
#include <mem/vmu_pde.h>

/** Kernel page directory */
extern struct page_directory *_kpage_dir;

/** Virtual address type (32 bit) */
typedef uint32_t virtual_addr;

/** X86 architecture defines 1024 entries per table. */
#define PAGES_PER_TABLE		1024
/** X86 architecture define 1024 entries per directory. */
#define PAGES_PER_DIR		1024

/** Page table represents 4mb address space. */
#define PAGE_TABLE_ADDR_SPACE_SIZE		0x400000

/** Directory table represents 4gb address space. */
#define DIR_TABLE_ADDR_SPACE_SIZE		0x100000000

/** Page sizes are 4k. */
#define PAGE_SIZE	4096

// ////// VIRTUAL ADDRESS PARSING MACROS ///////

/** 
* Macro for extraction offset into PAGE from virtual address. 
* Bits 0..11 of virtual address representing OFFSET inside PAGE.
*/
#define PAGE_OFFSET(x)	(x & 0xFFF)

/**
* Macro for extraction index into array of PAGE TABLEs ENTRIES (pages) of virtual address. 
* Bits 12..21 of virtual address representing page table entrie index.
*/
#define PAGE_TABLE_INDEX(x) (((x) >> 12) & 0x3FF)

/**
* Macro for extraction index into array of PAGE DIRECTORY ENTRIES (pages tables) of virtual address. 
* Bits 22..31 of virtual address representing page directory entrie index.
*/
#define PAGE_DIRECTORY_INDEX(x) (((x) >> 22) & 0x3FF)

/**
* Data structure representing one PAGE TABLE.
* It's array of 1024 pages (resp. page table entries).
*/
struct page_table {
	pte entries[PAGES_PER_TABLE];  /**< Array of pages (page table entries). */
};

/**
* Data structure representing one PAGE DIRECTORY.
* It's array of 1024 page tables (resp. page directory entries).
*/
struct page_directory {
	pde						entries[PAGES_PER_DIR];				/**< Array of page tables (page directory entries), physical addreses. */
	struct page_table*		entries_virt[PAGES_PER_DIR];		/**< Array of page tables (page directory entries), virtual addreses pointers. */
	physical_addr 			pbdr;								/**< Physical address of page_directory structure */

};


extern inline struct page_directory* vmu_create_page_dir();
extern struct page_table* vmu_clone_page_table(struct page_table *spt, uint32_t *phys_addr);
extern struct page_directory* vmu_clone_page_dir(struct page_directory *spd);
extern pde * vmu_page_dir_lookup(struct page_directory *pd, virtual_addr addr);
extern pte * vmu_page_table_lookup(struct page_table *pt, virtual_addr addr);
extern bool vmu_switch_page_dir(struct page_directory *pd);
extern void vmu_flush_tlb_entry(virtual_addr addr);
extern struct page_directory * vmu_get_current_page_dir();
extern bool vmu_alloc_page(pte *e);
extern pte * vmu_get_page(virtual_addr addr);
extern void vmu_free_page(pte *e);
extern void vmu_map_page(void* phys, void* virt);
extern void vmu_do_paging(bool p);
extern void vmu_load_PDBR(struct page_directory *p);
extern void vmu_init();




#endif
